/*******************************************************************************
 * Copyright (c) 2010 liw.
 * All rights reserved. 
 * 
 * This file is part of VanBus.
 * 
 *     VanBus is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 * 
 *     VanBus is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 * 
 *     You should have received a copy of the GNU General Public License
 *     along with VanBus.  If not, see <http://www.gnu.org/licenses/>.
 * Contributors:
 *     liw - initial API and implementation
 ******************************************************************************/
package org.niclab.vanbus.query;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

import org.niclab.vanbus.application.VanBusApplication;
import org.niclab.vanbus.preference.AppPreferences;
import org.niclab.vanbus.query.command.CommandChain;
import org.niclab.vanbus.query.command.ICommand;
import org.niclab.vanbus.query.command.ICommandChain;
import org.niclab.vanbus.query.handler.IQueryHandler;

import android.content.Context;

public abstract class AbstractQueryWorker implements IQueryWorker{
	
	//protected Context context;
	
	protected IQueryHandler asyncQueryHandler;
	protected IQueryHandler syncQueryHandler;
	
	protected CommandChain syncPreChain;
	protected CommandChain syncPostChain;
	
	
	
	
	protected LinkedHashSet<IQuery> queries = new LinkedHashSet<IQuery>();

	
	public AbstractQueryWorker(/*Context ctx*/){
		//this.context =ctx;
		this.syncPreChain = new CommandChain();
		this.syncPostChain = new CommandChain();
	}
	

	public void addSyncPreCmd(ICommand cmd){
		syncPreChain.addCommand(cmd);
	}
	

	public void addSyncPostCmd (ICommand cmd){
		syncPostChain.addCommand(cmd);
	}
	
	protected void executeSyncPreCommand(){
		syncPreChain.execute(null);
	}
	
	protected void executeSyncPostCommand(Object result){
		syncPostChain.execute(result);
	
	}



	
	public void addSyncQueryHandler(IQueryHandler handler){
		if(handler!=null)
			queries.add(handler.getQuery());
		
		if(this.syncQueryHandler!=null)
			this.syncQueryHandler.setNextQueryHandler(handler);
		else
			this.syncQueryHandler =handler;
		
	}
	
	public void removeSyncQueryHandler(){
		this.syncQueryHandler=null;
	}
	

	public void addAsyncQueryHandler(IQueryHandler handler){
		if(handler!=null)
			queries.add(handler.getQuery());
		IQueryHandler qHandler = this.asyncQueryHandler; 
		
		if(qHandler == null){
			this.asyncQueryHandler = handler;
			return;
		}
		while(qHandler.getNextQueryHandler() !=null){
			qHandler = qHandler.getNextQueryHandler();
		}
		qHandler.setNextQueryHandler(handler);

		
	}
	
	public IQueryHandler getAsyncQueryHandler() {
		return asyncQueryHandler;
	}

	public IQueryHandler getSyncQueryHandler() {
		return syncQueryHandler;
	}
	
	//if all the work is finished
	@Override
	public boolean isWorkFinished(){
		
		for(IQuery query: queries){
			if(!query.isQueryFinished())
				return false;
		}
		
		return true;
	}
	
	public IQuery getLastFinishedQuery(){
		IQuery lastQuery = null;
		for(IQuery query:queries){
			if (query.getQueryResult() != null)
				lastQuery = query;
			
			
		}
		
		return lastQuery;
	}
	
	
	public IQueryHandler getLastSyncQueryHandler(){
		IQueryHandler sync = this.getSyncQueryHandler();
		if (sync!=null){
			
			while(sync.getNextQueryHandler()!=null)
				sync = sync.getNextQueryHandler();
		}
		
		return sync;
		
	}
	
	public IQueryHandler getLastAsyncQueryHandler(){
		
		IQueryHandler async = this.getAsyncQueryHandler();
		if (async!=null){
			
			while(async.getNextQueryHandler()!=null)
				async = async.getNextQueryHandler();
		}
		
		return async;
	}
	
	public AbstractQueryWorker connectWorker(AbstractQueryWorker otherWorker){

		this.addSyncQueryHandler(otherWorker.getSyncQueryHandler());
		this.addAsyncQueryHandler(otherWorker.getAsyncQueryHandler());
		
		return this;
	}
}
